import { useState, useEffect, useRef } from 'react';

/**
 * 打字机效果的配置选项接口
 */
interface TypewriterOptions {
  speed?: number;        // 每个字符的延迟时间（毫秒）
  onComplete?: () => void; // 效果完成时的回调函数
}

/**
 * 自定义React Hook，用于实现打字机效果
 * @param text - 需要逐字显示的完整文本
 * @param isTyping - 控制是否开始打字过程的布尔值
 * @param options - 配置选项，如速度和完成回调
 * @returns {string} - 当前应显示的文本部分
 */
export const useTypewriter = (
  text: string,
  isTyping: boolean,
  options: TypewriterOptions = {}
) => {
  const { speed = 30, onComplete } = options;
  const [displayText, setDisplayText] = useState(''); // 最终在UI上显示的文本
  const [currentIndex, setCurrentIndex] = useState(0); // 当前显示到哪个字符的索引
  const intervalRef = useRef<NodeJS.Timeout | null>(null); // 定时器的引用
  
  // --- 核心逻辑：处理打字过程 ---
  useEffect(() => {
    // 1. 如果外部指令不是“打字中”，则直接显示完整文本
    if (!isTyping) {
      setDisplayText(text);
      setCurrentIndex(text.length);
      // 清理可能存在的定时器
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
      return;
    }
    
    // 2. 如果文本变长（例如，从API流式接收到新内容），则启动或继续打字
    if (text.length > currentIndex) {
      // 清除之前的定时器，以新的速度或文本长度重新开始
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
      
      // 3. 使用setInterval开始逐字显示
      intervalRef.current = setInterval(() => {
        // 更新当前索引，每次加一
        setCurrentIndex(prevIndex => {
          const nextIndex = prevIndex + 1;
          
          // 如果已显示完所有文本
          if (nextIndex >= text.length) {
            if (intervalRef.current) {
              clearInterval(intervalRef.current); // 清除定时器
              intervalRef.current = null;
            }
            return text.length; // 索引设置为最大值
          }
          
          // 返回下一个索引
          return nextIndex;
        });
      }, speed);
    }
    
    // 4. 清理函数：在组件卸载或依赖项变化时清除定时器
    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
    };
  }, [text, isTyping, speed, currentIndex]); // 依赖项包括currentIndex确保文本长度变化时能重新触发
  
  // --- 效果更新：根据索引更新显示的文本 ---
  useEffect(() => {
    // 根据当前索引，从完整文本中截取子字符串用于显示
    setDisplayText(text.substring(0, currentIndex));
    
    // 当打字完成时（索引达到文本末尾），调用onComplete回调
    if (currentIndex >= text.length && text.length > 0 && onComplete) {
      onComplete();
    }
  }, [currentIndex, text, onComplete]);
  
  // 返回当前应该显示的文本
  return displayText;
};
